package simorg;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.DecimalFormat;

class Test implements Comparable<Test> {
	private final boolean m_isDerivative;

	private final String m_description;

	private final DecimalFormat m_formatter = new DecimalFormat("0.0000");

	private final DecimalFormat m_shortFormatter = new DecimalFormat("0.00");
	private final int m_id;
	private final String m_name;
	private final int m_order;
	private final int m_timeMinutes;
	private final int m_weightIndex;
	private final String m_weightComment;

	private float m_classificationFactor;

	private float m_classificationFactorScore;
	private float m_discriminationFactor;
	private float m_discriminationFactorScore;
	private float m_timePenalty;
	private float m_weightFactor;

	public Test(final ResultSet a_row, final int a_id,
			final boolean a_isDerivative) {
		try {
			m_isDerivative = a_isDerivative;

			m_id = a_id;
			m_name = a_row.getString(2);
			m_timeMinutes = a_row.getInt(3);
			m_description = a_row.getString(4);
			m_order = a_row.getInt(5);

			// weight index is 1-based in input but 0-based as internal index
			m_weightIndex = a_row.getInt(6) - 1;
			m_weightComment = a_row.getString(7);

		} catch (final SQLException sqlex) {
			sqlex.printStackTrace();

			// invalid row
			throw new IllegalArgumentException();
		}
	}

	public int compareTo(final Test a_test) {

		// derivative tests are after classification tests
		if (isDerivative() && !a_test.isDerivative()) {
			return 1;
		}

		// classification tests are before derivative tests
		if (!isDerivative() && a_test.isDerivative()) {
			return -1;
		}

		// otherwise, compare by CF score
		final float myCf = getClassFactorScore();
		final float otherCf = a_test.getClassFactorScore();

		if (myCf == otherCf) {

			// fall back on DF
			final float myDf = getDiscrimFactorScore();
			final float otherDf = a_test.getDiscrimFactorScore();

			if (myDf > otherDf) {
				return -1;
			} else if (myDf == otherDf) {
				return 0;
			} else {
				return 1;
			}
		} else if (myCf > otherCf) {
			return -1;
		} else {
			return 1;
		}
	}

	public String getAllDataAsTableRow() {
		if (getClassFactorScore() > 0.0f || getDiscrimFactorScore() > 0.0f) {
			return (getWeightIndex() + 1) + "\t\t"
					+ m_shortFormatter.format(getWeightFactor()) + "\t"
					+ getTimeMinutes() + "\t\t"
					+ m_formatter.format(getTimePenalty()) + "\t\t"
					+ m_formatter.format(getClassificationFactor()) + "\t\t"
					+ m_formatter.format(getClassFactorScore()) + "\t\t"
					+ m_formatter.format(getDiscrimFactor()) + "\t\t"
					+ m_formatter.format(getDiscrimFactorScore()) + "\t\t"
					+ getFullName() + "\n";
		}

		return "";
	}

	public float getClassFactorScore() {
		return m_classificationFactorScore;
	}

	public float getClassificationFactor() {
		return m_classificationFactor;
	}

	public String getDescription() {
		return m_description;
	}

	public float getDiscrimFactor() {
		return m_discriminationFactor;
	}

	public float getDiscrimFactorScore() {
		return m_discriminationFactorScore;
	}

	public String getFullName() {
		return "'" + getName().toLowerCase() + "' ("
				+ (isDerivative() ? "D" : "T") + m_id + ")";
	}

	public int getId() {
		return m_id;
	}

	public String getName() {
		return m_name;
	}

	public int getOrder() {
		return m_order;
	}

	public int getTimeMinutes() {
		return m_timeMinutes;
	}

	public float getTimePenalty() {
		return m_timePenalty;
	}

	public String getWeightComment() {
		return m_weightComment;
	}

	public float getWeightFactor() {
		return m_weightFactor;
	}

	public int getWeightIndex() {
		return m_weightIndex;
	}

	public boolean isDerivative() {
		return m_isDerivative;
	}

	public void setClassFactor(final float a_classificationFactor) {
		m_classificationFactor = a_classificationFactor;
	}

	public void setClassFactorScore(final float a_classificationFactorScore) {
		m_classificationFactorScore = a_classificationFactorScore;
	}

	public void setDiscrimFactor(final float a_discriminationFactor) {
		m_discriminationFactor = a_discriminationFactor;
	}

	public void setDiscrimFactorScore(final float a_discriminationFactorScore) {
		m_discriminationFactorScore = a_discriminationFactorScore;
	}

	public void setTimePenalty(final float a_timePenalty) {
		m_timePenalty = a_timePenalty;
	}

	public void setWeightFactor(final float a_weightFactor) {
		m_weightFactor = a_weightFactor;
	}

	@Override
	public String toString() {
		return m_name;
	}
}